package com.ylr.basic.framework.service.impl;

import com.ylr.basic.common.enums.BasicResultEnum;
import com.ylr.basic.framework.entity.EphemeralDataEntity;
import com.ylr.basic.framework.mapper.EphemeralDataMapper;
import com.ylr.basic.framework.service.EphemeralDataService;
import com.ylr.base.common.constant.Constant;
import com.ylr.base.common.enums.CommonEnum;
import com.ylr.base.common.exception.YlrException;
import com.ylr.base.common.po.user.UserPo;
import com.ylr.base.common.utils.DataUtils;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.ylr.basic.common.dto.EphemeralDataDto;
import com.ylr.basic.common.enums.BusinessTypeEnum;
import com.ylr.base.common.utils.UserUtils;
import com.ylr.basic.common.vo.ephemeral_data.EphemeralDataQueryVo;
import com.ylr.basic.common.vo.ephemeral_data.EphemeralDataVo;
import com.ylr.base.framework.service.SnowflakeService;
import lombok.AllArgsConstructor;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;

/**
 * Created by IntelliJ IDEA.
 *
 * @author wyw
 * date: 2023-07-06 22:41:05
 * className: EphemeralDataServiceImpl
 * version: 1.0
 * description:
 */
@Service("ephemeralDataService")
@AllArgsConstructor
public class EphemeralDataServiceImpl extends ServiceImpl<EphemeralDataMapper, EphemeralDataEntity> implements EphemeralDataService {

    private static final Logger log = LoggerFactory.getLogger(EphemeralDataServiceImpl.class);

    private final SnowflakeService snowflakeService;

    @Override
    public void saveEphemeralData(EphemeralDataVo ephemeralDataVo) {
        // 数据构造
        EphemeralDataEntity ephemeralData = this.newEphemeralData(ephemeralDataVo);
        // 保存数据
        baseMapper.insert(ephemeralData);
        log.info("临时数据保存完成");
    }

    @Override
    public EphemeralDataDto getEphemeralData(Long businessId, Integer businessType) {

        LambdaQueryWrapper<EphemeralDataEntity> ephemeralDataLambdaQueryWrapper = new LambdaQueryWrapper<>();
        // 匹配条件
        ephemeralDataLambdaQueryWrapper.eq(EphemeralDataEntity::getBusinessId, businessId)
                .eq(EphemeralDataEntity::getBusinessType, businessType)
                .eq(EphemeralDataEntity::getDeleteStatus, CommonEnum.DELETE_NO.getValue());
        // 排序
        ephemeralDataLambdaQueryWrapper.orderByDesc(EphemeralDataEntity::getId);
        // 限制查询个数
        ephemeralDataLambdaQueryWrapper.last("limit 1");
        // 查询数据
        List<EphemeralDataEntity> ephemeralDataList = baseMapper.selectList(ephemeralDataLambdaQueryWrapper);
        if (ephemeralDataList.isEmpty()) {
            log.info("临时数据为空");
            return null;
        }
        EphemeralDataEntity ephemeralData = ephemeralDataList.get(0);
        if (!Long.valueOf(-1).equals(ephemeralData.getExpire())
                && ephemeralData.getExpire().compareTo(System.currentTimeMillis()) <= 0) {
            log.info("临时数据已过期。expire={}", ephemeralData.getExpire());
            return null;
        }
        // 数据封装
        return this.getEphemeralDataDto(ephemeralData);
    }

    @Override
    public List<EphemeralDataDto> batchGetEphemeralData(EphemeralDataQueryVo ephemeralDataQueryVo) {

        LambdaQueryWrapper<EphemeralDataEntity> ephemeralDataLambdaQueryWrapper = new LambdaQueryWrapper<>();
        // 匹配条件
        ephemeralDataLambdaQueryWrapper.eq(EphemeralDataEntity::getBusinessId, ephemeralDataQueryVo.getBusinessId())
                .in(EphemeralDataEntity::getBusinessType, ephemeralDataQueryVo.getBusinessTypeList())
                .eq(EphemeralDataEntity::getDeleteStatus, CommonEnum.DELETE_NO.getValue());
        // 查询数据
        List<EphemeralDataEntity> ephemeralDataList = baseMapper.selectList(ephemeralDataLambdaQueryWrapper);
        if (ephemeralDataList.isEmpty()) {
            log.info("临时数据为空");
            return Collections.emptyList();
        }

        long now = System.currentTimeMillis();
        Long negative = Constant.NEGATIVE_ONE.longValue();
        StringBuilder sb = new StringBuilder();
        sb.append(ephemeralDataQueryVo.getBusinessId());
        sb.append(Constant.SPLIT);
        int start = sb.length();

        return new ArrayList<>(ephemeralDataList.stream()
                // 过滤掉已过期的数据
                .filter(ephemeralData -> negative.equals(ephemeralData.getExpire()) || ephemeralData.getExpire().compareTo(now) >= 0)
                // 先根据主键进行排序，保证数据顺序，为后续取最新数据做铺垫
//                .sorted(Comparator.comparing(EphemeralDataEntity::getId))
                .map(this::getEphemeralDataDto)
                .collect(Collectors.toMap(
                        ephemeralDataDto -> DataUtils.replaceStringBuilder(sb, start, String.valueOf(ephemeralDataDto.getBusinessType())).toString(),
                        Function.identity(),
                        (o1, o2) -> o2)
                )
                .values()
        );
    }

    @Override
    public void deleteEphemeralData(List<Long> idList) {

        LambdaUpdateWrapper<EphemeralDataEntity> ephemeralDataLambdaUpdateWrapper = new LambdaUpdateWrapper<>();
        // 设置字段值
        ephemeralDataLambdaUpdateWrapper.set(EphemeralDataEntity::getDeleteStatus, CommonEnum.DELETE_YES.getValue());
        // 匹配条件
        ephemeralDataLambdaUpdateWrapper.in(EphemeralDataEntity::getId, idList)
                .eq(EphemeralDataEntity::getDeleteStatus, CommonEnum.DELETE_NO.getValue());
        // 更新数据
        int count = baseMapper.update(null, ephemeralDataLambdaUpdateWrapper);
        log.info("临时数据删除完成。count={}", count);

    }

    @Override
    public void deleteEphemeralData(Long businessId, Integer businessType) {
        LambdaUpdateWrapper<EphemeralDataEntity> ephemeralDataLambdaUpdateWrapper = new LambdaUpdateWrapper<>();
        // 设置字段值
        ephemeralDataLambdaUpdateWrapper.set(EphemeralDataEntity::getDeleteStatus, CommonEnum.DELETE_YES.getValue());
        // 匹配条件
        ephemeralDataLambdaUpdateWrapper.in(EphemeralDataEntity::getBusinessId, businessId)
                .eq(EphemeralDataEntity::getBusinessType, businessType)
                .eq(EphemeralDataEntity::getDeleteStatus, CommonEnum.DELETE_NO.getValue());
        // 更新数据
        int count = baseMapper.update(null, ephemeralDataLambdaUpdateWrapper);
        log.info("临时数据删除完成。count={}", count);
    }

    /**
     * 生成临时数据实体对象
     * @param ephemeralDataVo 参数对象
     * @return 临时数据实体对象
     */
    private EphemeralDataEntity newEphemeralData(EphemeralDataVo ephemeralDataVo) {
        // 获取业务类型枚举对象
        BusinessTypeEnum businessTypeEnum = BusinessTypeEnum.getBusinessTypeEnum(ephemeralDataVo.getBusinessType());
        if (Objects.isNull(businessTypeEnum)) {
            throw new YlrException(BasicResultEnum.BUSINESS_TYPE_FAIL);
        }
        // 查询最大版本号
        Integer maxVersion = baseMapper.selectMaxVersion(ephemeralDataVo.getBusinessId(), ephemeralDataVo.getBusinessType(),
                CommonEnum.DELETE_NO.getValue());
        if (Objects.isNull(maxVersion)) {
            maxVersion = Constant.ZERO;
        }
        maxVersion += 1;

        Long userId = CommonEnum.DEFAULT_ID.getLongValue();
        String username = StringUtils.EMPTY;
        // 获取正在保存临时数据的用户
        UserPo userPo = UserUtils.getUser();
        if (Objects.nonNull(userPo)) {
            userId = userPo.getId();
            username = userPo.getUsername();
        }

        EphemeralDataEntity ephemeralData = new EphemeralDataEntity();
        ephemeralData.setId(snowflakeService.getId())
                .setBusinessId(ephemeralDataVo.getBusinessId())
                .setBusinessType(ephemeralDataVo.getBusinessType())
                .setBusinessValue(ephemeralDataVo.getBusinessValue())
                .setExpire(
                        Optional.of(businessTypeEnum.getExpireMillis())
                                .filter(expireMills -> expireMills.compareTo(0L) > 0)
                                .map(expireMills -> expireMills + System.currentTimeMillis())
                                .orElse(-1L)
                )
                .setVersion(maxVersion)
                .setDeleteStatus(CommonEnum.DELETE_NO.getValue())
                .setCreateTime(new Date())
                .setCreateUser(username)
                .setCreateUserId(userId);
        return ephemeralData;
    }

    /**
     * 临时数据实体对象封装
     * @param ephemeralData 临时数据实体对象
     * @return 封装结果
     */
    public EphemeralDataDto getEphemeralDataDto(EphemeralDataEntity ephemeralData) {
        EphemeralDataDto ephemeralDataDto = new EphemeralDataDto();
        ephemeralDataDto.setId(Optional.ofNullable(ephemeralData.getId()).map(Objects::toString).orElse(null))
                .setBusinessId(Optional.ofNullable(ephemeralData.getBusinessId()).map(Objects::toString).orElse(null))
                .setBusinessType(ephemeralData.getBusinessType())
                .setBusinessValue(ephemeralData.getBusinessValue())
                .setExpire(
                        Optional.ofNullable(ephemeralData.getExpire())
                                .filter(expire -> expire.compareTo(0L) > 0)
                                .map(Date::new)
                                .orElse(null)
                )
                .setVersion(ephemeralData.getVersion());
        return ephemeralDataDto;
    }
}